home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / System 7.0 Samples / Edition Manager / Menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-18  |  20.9 KB  |  536 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  *
  3.  *  Apple Developer Technical Support
  4.  *
  5.  *  Menu handling routines
  6.  *
  7.  *  Program:    EditionSample
  8.  *  File:       Menu.c -    C Source
  9.  *
  10.  *  by:         C.K. Haun <TR>
  11.  *
  12.  *  Copyright © 1990,1991 Apple Computer, Inc.
  13.  *  All rights reserved.
  14.  *
  15.  *------------------------------------------------------------------------------
  16.  * This file handles menu stuff, swapping checkmarks, handling simple dialog 
  17.  * boxes, and the like.  If it happens because of a menu selection, it comes through
  18.  * here.
  19.  *----------------------------------------------------------------------------*/
  20.  
  21. #define __SAMPMENU__
  22.  
  23. #pragma segment Main
  24. #pragma load "EdSampheaders"                                /* see the Buildheaders.c file */
  25.  
  26. #include "EdSampdefines.h"
  27.  
  28. /* prototypes */
  29. void StartMenus();
  30. void SetUndo(short undoNow, Boolean fromRecord);
  31. Boolean DoSelected(long val);
  32. void SetCurAction(short actionIn);
  33. void DoDaCall(MenuHandle themenu, long theit);
  34. void SwitchChecks(short itemNow);
  35. void SetMyCursor(short myCurs);
  36. void SetWMenus(Boolean how);
  37. OSErr PrepQuit(void);
  38. void AdjustMenus(windowCHandle tempCH);
  39. /* external references */
  40. extern Handle gMymenu;
  41. extern MenuHandle gAppleMenuHandle, gFileMenuHandle, gEditMenuHandle, gToolMenuHandle, gAdditionalMenu;
  42. extern Boolean gStop;
  43. extern void SaveMe(windowCHandle theWind, WindowPtr theWindPtr);
  44. extern void CloseClip(void);
  45. extern WindowPtr OpenFile(FSSpec *inSpec);
  46. extern void UndoLast(void);
  47. extern WindowPtr AddNewWindow(Boolean showIt);
  48. extern void DoOptions(SectionHandle inSection);
  49. extern void DeleteSubscriber(void);
  50. extern void PasteSubscription(void);
  51. extern void CutSubscription(void);
  52. extern void CopySubscription(void);
  53. extern void PrintIt(WindowPtr theWind, Boolean keepOpen);
  54. extern OSErr CreatePublisher(OSType typeToMake,Boolean fromEvent,AliasHandle theAlias);
  55. extern Boolean HasTESelection(windowCHandle inWind);
  56. extern Boolean PasteText(void);
  57. extern Boolean CutText(void);
  58. extern Boolean CopyText(void);
  59. extern Boolean ClearText(void);
  60.  
  61. extern WindowPtr gActionWindows;
  62. extern WindowPtr gClipWindowPtr;
  63. short gWindowCount;
  64. extern Boolean gExpanded;
  65. extern Boolean gEdSamp;
  66. extern Boolean gShowingAll;
  67. Str255 undoString;                                          /* for the current Undo menu item text */
  68. short pItemChecked;
  69. extern SectionHandle gShowingSecHandle;
  70. extern WindowPtr gCurrentWindow;
  71. /* file globals */
  72. CursHandle pCursHand = nil;
  73. extern Boolean gHasSelection;
  74. extern Boolean gShowPub;
  75. extern Boolean gShowSub;
  76. extern short gClipHasContents;
  77. /* StartMenus loads our menu bar resource, and initializes the menus 
  78. *   and some settings related to the menu items 
  79. */
  80. /* and since it's an initializer, I'll put it in that segement */
  81. #pragma segment MyInit
  82. void StartMenus(void)
  83. {
  84.     gMymenu = GetNewMBar(kOurMenuBar);
  85.     SetMenuBar(gMymenu);
  86.     DrawMenuBar();
  87.     gAppleMenuHandle = GetMenuHandle(kAppleMenu);
  88.     gFileMenuHandle = GetMenuHandle(kFileMenu);
  89.     gEditMenuHandle = GetMenuHandle(kEditMenu);
  90.     gToolMenuHandle = GetMenuHandle(kToolsMenu);
  91.     gAdditionalMenu = GetMenuHandle(kAdditionalMenu);
  92.     AppendResMenu(gAppleMenuHandle, 'DRVR');                   /* add DAs */
  93. }
  94.  
  95. /* end StartMenus */
  96.  
  97. #pragma segment Main
  98. /* DoSelected is called from the main event loop in response to a 
  99. *   MenuSelect or MenuKey action.  Some events are handled here,
  100. *   some just set options.
  101. */
  102.  
  103. Boolean DoSelected(long val)
  104. {
  105.     short loval, hival;
  106.     Boolean temp = false;
  107.     short tempActionOut;
  108.     loval = LoWord(val);
  109.     hival = HiWord(val);
  110.     HiliteMenu(0);
  111.     switch (hival) {                                        /* switch off the menu number selected */
  112.         case kAppleMenu:                                    /* Apple menu */
  113.             if (loval != 1) {                               /* if this was not About, it's a DA */
  114.                 DoDaCall(gAppleMenuHandle, loval);
  115.             } else {
  116.                 Alert(128, nil);                            /* do about box */
  117.             }
  118.             break;
  119.         case kFileMenu:                                     /* File menu */
  120.             switch (loval) {
  121.                 WindowPtr tempW;
  122.                 AliasHandle tempAlias;                      /* for SaveAs */
  123.                 windowCHandle tempName;
  124.                 case kNewItem:
  125.                     if (!(tempW = AddNewWindow(true)))      /* Call AddNewWindow.  If it fails, tell */
  126.                         Alert(kNoMoreWindows, nil);         /* user why */
  127.                     else
  128.                         ChangePlane(tempW);
  129.                     break;
  130.                 case kOpenItem:
  131.                     OpenFile(nil);                          /* open a file, nil says that I am not passing a */
  132.                     /* FileSpec, promt the user for a name */
  133.                     break;
  134.                 case kCloseItem:                            /* call the close procedure for this window */
  135.                     (ProcPtr)((*(windowCHandle)((WindowPeek)gCurrentWindow)->refCon)->closeMe)(gCurrentWindow);
  136.                     break;
  137.                 case kSaveItem:                             /* call the save procedure for this window */
  138.                     HLock((Handle)(windowCHandle)((WindowPeek)gCurrentWindow)->refCon);
  139.                     (ProcPtr)(*
  140.                         ((windowCHandle)((WindowPeek)gCurrentWindow)->refCon))->
  141.                     saveMe((windowCHandle)((WindowPeek)gCurrentWindow)->refCon, gCurrentWindow);
  142.                     HUnlock((Handle)(windowCHandle)((WindowPeek)gCurrentWindow)->refCon);
  143.                     break;
  144.                 case kSaveAsItem:                           /* save under a different name */
  145.                     HLock((Handle)(windowCHandle)((WindowPeek)gCurrentWindow)->refCon);
  146.                     tempName = (windowCHandle)GetWRefCon(gCurrentWindow);
  147.                     /* save off the old alias in case the person cancels */
  148.                     tempAlias = (*tempName)->fileAliasHandle;
  149.                     /* get an empty handle and store it in the alias place, this tells the Save */
  150.                     /* function that this file has not yet been saved, so put up a SF box */
  151.                     (*tempName)->fileAliasHandle = (AliasHandle)NewHandle(0);
  152.                     (ProcPtr)(*
  153.                         ((windowCHandle)((WindowPeek)gCurrentWindow)->refCon))->
  154.                     saveMe((windowCHandle)((WindowPeek)gCurrentWindow)->refCon, gCurrentWindow);
  155.                     /* see if they really saved (by checking the size of the alias) and if they have */
  156.                     /* get rid of the alias you saved */
  157.                     if (GetHandleSize((Handle)(*tempName)->fileAliasHandle) == nil) {
  158.                         DisposeHandle((Handle)(*tempName)->fileAliasHandle);
  159.                         (*tempName)->fileAliasHandle = tempAlias;
  160.                     } else {
  161.                         DisposeHandle((Handle)tempAlias);
  162.                     }
  163.                     HUnlock((Handle)(windowCHandle)((WindowPeek)gCurrentWindow)->refCon);
  164.                     break;
  165.                     
  166.                 case kPrintItem:
  167.                     PrintIt(gCurrentWindow, true);
  168.                     break;
  169.                 case kQuitItem:
  170.                     PrepQuit();                             /* Call PrepQuit, which sets our quit flag, so we */
  171.                     /* quit the next time through the event loop. The */
  172.                     /* AEQuit handler also calls this routine */
  173.                     break;
  174.             }
  175.             break;
  176.         case kEditMenu:
  177.             /* edit menu junk */
  178.             switch (loval) {
  179.                 case kUndoItem:
  180.                     UndoLast();                             /* Undoes the last action in the frontmost window */
  181.                     break;
  182.                     /* all the C/C/P stuff acts _first_ on any active TextEdit records. */
  183.                     /* if there aren't any, then it goes to other stuff */
  184.                 case kCutItem:
  185.                     if (!CutText())
  186.                         CutSubscription();
  187.                     break;
  188.                 case kCopyItem:
  189.                     if (!CopyText())
  190.                         CopySubscription();
  191.                     break;
  192.                 case kPasteItem:
  193.                     /* pasting text has precidence over subscriptions.  Just because I felt like it */
  194.                     /* vary to suit the needs of your users and application */
  195.                     if (!PasteText())
  196.                         PasteSubscription();
  197.                     break;
  198.                 case kClearItem:
  199.                     /* Clear item acts as 'cancel' for the selected section */
  200.                     if (!ClearText())
  201.                         DeleteSubscriber();
  202.                     break;
  203.                 case kPublishItem:
  204.                     /* see if there is any text */
  205.                     if (HasTESelection((windowCHandle)GetWRefCon(FrontWindow())))
  206.                         CreatePublisher('TEXT',false,nil);
  207.                     else
  208.                         CreatePublisher('PICT',false,nil);            /* in Publish.c */
  209.                     break;
  210.                 case kSubscribeItem:
  211.                     DoSubscribe();                          /* in Subscribe.c */
  212.                     break;
  213.                 case kSoptionsItem:
  214.                     DoOptions(gShowingSecHandle);           /* in Subscribe.c.  Same */
  215.                     /* function is called for a publish or subscribe section */
  216.                     break;
  217.                 case kBorders:
  218.                     if (gShowingAll) {
  219.                         gShowingAll = false;
  220.                         SetMenuItemText(gEditMenuHandle, kBorders, "\pShow Borders");
  221.                     } else {
  222.                         gShowingAll = true;
  223.                         SetMenuItemText(gEditMenuHandle, kBorders, "\pHide Borders");
  224.                     }
  225.                     /* make sure they get redrawn */
  226.                     InvalRect(&(gCurrentWindow->portRect));
  227.                     
  228.                     break;
  229.                 case kClapNum:
  230.                     if (((WindowPeek)gClipWindowPtr)->visible) {
  231.                         CloseClip();
  232.                     } else {
  233.                         ShowWindow(gClipWindowPtr);
  234.                         ChangePlane(gClipWindowPtr);
  235.                         SetMenuItemText(gEditMenuHandle, kClapNum, "\pHide Clipboard");
  236.                         
  237.                     }
  238.                     break;
  239.                     /* TEST TEMP ••••• */
  240.                 case kClapNum + 1:
  241.                     /* TEST TEMP highlight the selection please */
  242.                     do {
  243.                         windowCHandle temp = (windowCHandle)GetWRefCon(FrontWindow());
  244.                         TEHandle theTEHandle = (*temp)->boxHandle;
  245.                         textSectionHandle currentSection = (*temp)->textSections;
  246.                         TESetSelect((*currentSection)->startChar, (*currentSection)->endChar, theTEHandle);
  247.                     } while (false);
  248.                     temp = true;
  249.                     break;
  250.                 default:
  251.                     Alert(132, nil);                        /* TEST TEMP */
  252.                     break;
  253.                     
  254.             }                                               /* edit menu switch */
  255.             break;
  256.         case kToolsMenu:
  257.             switch (loval) {
  258.                 /* Clean this up, this is silly, I say, this is silly son..... */
  259.                 case kLineItem:
  260.                     tempActionOut = kDrawLine;
  261.                     break;
  262.                 case kRectItem:
  263.                     tempActionOut = kDrawRect;
  264.                     break;
  265.                 case kOvalItem:
  266.                     tempActionOut = kDrawOval;
  267.                     break;
  268.                 case kTextBoxItem:
  269.                     tempActionOut = kTextBox;
  270.                     break;
  271.                 case kSelectItem:
  272.                     tempActionOut = kSelectStuff;
  273.                     break;
  274.             }
  275.             /* these set the current action for the front window, set the */
  276.             /* cursor for the selected tool, and check the correct menu item */
  277.             SetCurAction(tempActionOut);
  278.             SetMyCursor(loval);
  279.             SwitchChecks(loval);
  280.             break;
  281.         case kAdditionalMenu:
  282.             switch (loval) {
  283.                 EditionInfoRecord tempRecord;
  284.                 Str255 orgDate;
  285.                 Str255 modDate;
  286.                 char parm1[5];
  287.                 char parm2[5];
  288.                 case kExpandedItem:
  289.                     if (gExpanded)
  290.                         gExpanded = false;
  291.                     else
  292.                         gExpanded = true;
  293.                     CheckItem(gAdditionalMenu, kExpandedItem, gExpanded);
  294.                     
  295.                     break;
  296.                 case kGetSecInfo:
  297.                     GetEditionInfo(gShowingSecHandle, &tempRecord);
  298.                     IUDateString(tempRecord.crDate, longDate, orgDate);
  299.                     IUDateString(tempRecord.mdDate, longDate, modDate);
  300.                     parm1[0] = 4;
  301.                     parm2[0] = 4;
  302.                     BlockMove((Ptr)&tempRecord.fdCreator, (Ptr)&parm1[1], 4);
  303.                     BlockMove((Ptr)&tempRecord.fdType, (Ptr)&parm2[1], 4);
  304.                     ParamText(orgDate, modDate, parm1, parm2);
  305.                     Alert(kEdInfo, nil);
  306.                     break;
  307.                 case kEdSampFiles:
  308.                     if (gEdSamp)
  309.                         gEdSamp = false;
  310.                     else
  311.                         gEdSamp = true;
  312.                     CheckItem(gAdditionalMenu, kEdSampFiles, gEdSamp);
  313.                     break;
  314.             }
  315.             break;
  316.     }
  317.     return(temp);
  318. }
  319.  
  320. /* end DoSelected */
  321.  
  322. /* DoDaCall opens the requested DA.  It's here as a seperate routine if you'd */
  323. /* like to perform some action or just know when a DA is opened in your */
  324. /* layer.  Can be handy to track memory problems when a DA is opened */
  325. /* with an Option-open */
  326. void DoDaCall(MenuHandle themenu, long theit)
  327. {
  328.     long qq;
  329.     char DAname[255];
  330.     GetMenuItemText(themenu, theit, &DAname);
  331.     qq = OpenDeskAcc(DAname);
  332. }
  333.  
  334. /* end DoDaCall */
  335.  
  336.  
  337. /* PrepQuit sets the stop flag.  Called from the menu or from the */
  338. /* quit AppleEvent handler.  It also calls the close function on all open windows, and */
  339. /* cancels the quit if a cancel happened */
  340. /* Also unregisters the ClipBoard section, if one exists */
  341. OSErr PrepQuit(void)
  342. {
  343.     gStop = true;
  344.     while (gWindowCount) {
  345.         CloseMyWindow(gActionWindows);                      /* step through until all are closed */
  346.         if (gStop == false)
  347.             break;                                          /* if this is false, they hit cancel in the close routine */
  348.     }
  349.     if (gStop) {
  350.         extern short gClipHasContents;
  351.         extern SectionHandle gClipSection;
  352.         /* clear the clipboard */
  353.         if (gClipHasContents == kClipHasSub) {
  354.             UnRegisterSection(gClipSection);
  355.             DisposeHandle((Handle)(*gClipSection)->alias);
  356.             DisposeHandle((Handle)gClipSection);
  357.             gClipSection = nil;
  358.             gClipHasContents = kClipEmpty;
  359.         }
  360.         return(noErr);                                      /* quit will happen */
  361.     } else {
  362.         return(userCanceledErr);
  363.     }                                                       /* user stopped the termination */
  364. }
  365.  
  366. /* end PrepQuit */
  367.  
  368. /* SetUndo sets the text of the Undo item based on the last action in */
  369. /* the current window, if fromRecord is true, else use*/
  370. /* undoNow */
  371. void SetUndo(short undoNow, Boolean fromRecord)
  372. {
  373.     windowCHandle temp;
  374.     if (gCurrentWindow == nil) {
  375.         GetIndString(undoString, kUndoStringsRes, 1);
  376.         SetMenuItemText(gEditMenuHandle, kUndoItem, &undoString);
  377.         DisableItem(gEditMenuHandle, kUndoItem);
  378.     } else {
  379.         temp = (windowCHandle)GetWRefCon(gCurrentWindow);
  380.         if (fromRecord)
  381.             undoNow = (*temp)->undoAction;
  382.         else
  383.             (*temp)->undoAction = undoNow;
  384.         GetIndString(undoString, kUndoStringsRes, undoNow + 1);
  385.         SetMenuItemText(gEditMenuHandle, kUndoItem, &undoString);
  386.         if (undoNow)
  387.             EnableItem(gEditMenuHandle, kUndoItem);
  388.         else
  389.             DisableItem(gEditMenuHandle, kUndoItem);
  390.     }
  391. }
  392.  
  393. /* end SetUndo */
  394.  
  395. /* SetMyCursor sets the cursor to the correct shape for the */
  396. /* tool in use */
  397. void SetMyCursor(short myCurs)
  398. {
  399.     if (pCursHand != nil) {
  400.         ReleaseResource((Handle)pCursHand);
  401.         pCursHand = nil;
  402.     }
  403.     if (myCurs == 0) {
  404.         InitCursor();
  405.     } else {
  406.         switch (myCurs) {
  407.             case kLineItem:
  408.                 pCursHand = GetCursor(crossCursor);
  409.                 break;
  410.             case kRectItem:
  411.             case kTextBox:
  412.             case kOvalItem:
  413.                 pCursHand = (CursHandle)GetResource('CURS', 126 + myCurs);
  414.                 break;
  415.             case kSelectItem:
  416.                 pCursHand = (CursHandle)GetResource('CURS', 131);
  417.                 break;
  418.         }
  419.         SetCursor(*pCursHand);
  420.     }
  421. }
  422.  
  423. /* end SetMyCursor */
  424.  
  425. /* SwitchChecks sets the checking of the tool menu items  */
  426. void SwitchChecks(short itemNow)
  427. {
  428.     Boolean how;
  429.     if (pItemChecked == itemNow) {                          /* is this item currently checked?  If so */
  430.         how = false;                                        /* uncheck it and set action to nil */
  431.         SetCurAction(kNoAction);
  432.         InitCursor();
  433.         pItemChecked = 0;
  434.     } else {
  435.         CheckItem(gToolMenuHandle, pItemChecked, false);
  436.         pItemChecked = itemNow;
  437.         how = true;
  438.     }
  439.     CheckItem(gToolMenuHandle, itemNow, how);
  440. }
  441.  
  442. /* end SwitchChecks */
  443.  
  444. /* SetCurAction sets the action value in the window record */
  445. void SetCurAction(short actionIn)
  446. {
  447.     if (gCurrentWindow != nil) {
  448.         windowCHandle shortname = (windowCHandle)GetWRefCon(gCurrentWindow);
  449.         HLock((Handle)shortname);
  450.         (*shortname)->currentAction = actionIn;
  451.         HUnlock((Handle)shortname);
  452.     }
  453. }
  454.  
  455. /* end SetCurAction */
  456.  
  457. void SetWMenus(Boolean how)
  458. {
  459.     register qq;
  460.     if (how) {
  461.         EnableItem(gFileMenuHandle, kCloseItem);
  462.         EnableItem(gFileMenuHandle, kPrintItem);
  463.         EnableItem(gFileMenuHandle, kSaveItem);
  464.         EnableItem(gFileMenuHandle, kSaveAsItem);
  465.         EnableItem(gEditMenuHandle, kSubscribeItem);
  466.         EnableItem(gToolMenuHandle, 0);
  467.         for (qq = 1; qq < 5; qq++) {
  468.             EnableItem(gToolMenuHandle, qq);
  469.         }
  470.     } else {
  471.         DisableItem(gFileMenuHandle, kCloseItem);
  472.         DisableItem(gFileMenuHandle, kPrintItem);
  473.         DisableItem(gFileMenuHandle, kSaveItem);
  474.         DisableItem(gFileMenuHandle, kSaveAsItem);
  475.         DisableItem(gEditMenuHandle, kSubscribeItem);
  476.         DisableItem(gToolMenuHandle, 0);                    /* kill this whole thing */
  477.     }
  478.     DrawMenuBar();
  479. }
  480.  
  481. /* end SetWMenus */
  482.  
  483. void AdjustMenus(windowCHandle tempCH)
  484. {
  485.     register qq;
  486.     /* Do we currently */
  487.     /* have an area selected? */
  488.     if (gHasSelection || HasTESelection(tempCH))            /* Yes, enable the Publish item */
  489.         EnableItem(gEditMenuHandle, kPublishItem);
  490.     else                                                    /* No, dim the publish item */
  491.         DisableItem(gEditMenuHandle, kPublishItem);
  492.     /* Next, are we showing a border around a subscriber or */
  493.     /* publisher? If so, then we allow the user to bring up */
  494.     /* the Options dialog */
  495.     if (gShowPub || gShowSub) {
  496.         EnableItem(gEditMenuHandle, kSoptionsItem);
  497.         EnableItem(gAdditionalMenu, kGetSecInfo);
  498.     } else {
  499.         DisableItem(gEditMenuHandle, kSoptionsItem);
  500.         DisableItem(gAdditionalMenu, kGetSecInfo);
  501.     }
  502.     if (!(FrontWindow() == gClipWindowPtr) && (gCurrentWindow != nil)) {        /* is there a document window in front? */
  503.         EnableItem(gFileMenuHandle, kSaveItem);
  504.         if (GetHandleSize((Handle)(*tempCH)->fileAliasHandle) == nil)
  505.             SetMenuItemText(gFileMenuHandle, kSaveItem, "\pSave...");
  506.         else
  507.             SetMenuItemText(gFileMenuHandle, kSaveItem, "\pSave");
  508.         /* I'm only allowing a text box if there are no other objects. */
  509.         if ((*tempCH)->boxHandle != nil || (*tempCH)->ovalCount != 0 || (*tempCH)->rectCount != 0 || (*tempCH)->lineCount != 0)
  510.             DisableItem(gToolMenuHandle, kTextBoxItem);
  511.         else
  512.             EnableItem(gToolMenuHandle, kTextBoxItem);
  513.         
  514.     } else {
  515.         DisableItem(gFileMenuHandle, kSaveItem);
  516.     }
  517.     /* if there is a subscriber, or a subscription on the clipboard, or a TEselection enable the edit commands */
  518.     if (gShowSub || HasTESelection(tempCH)) {
  519.         EnableItem(gEditMenuHandle, kCutItem);
  520.         EnableItem(gEditMenuHandle, kCopyItem);
  521.         EnableItem(gEditMenuHandle, kClearItem);
  522.     } else {
  523.         DisableItem(gEditMenuHandle, kCutItem);
  524.         DisableItem(gEditMenuHandle, kCopyItem);
  525.         DisableItem(gEditMenuHandle, kClearItem);
  526.     }
  527.     if (gClipHasContents == kClipHasSub || (gClipHasContents == kClipHasText && (*tempCH)->boxHandle != nil) && (tempCH != nil)) {
  528.         EnableItem(gEditMenuHandle, kPasteItem);
  529.     } else {
  530.         DisableItem(gEditMenuHandle, kPasteItem);
  531.     }
  532. }
  533.  
  534.  
  535. #undef __SAMPMENU__
  536.